/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.toolkit;

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import who.tmap.bo.BaseMap;
import who.tmap.bo.ThematicMap;
import who.tmap.common.TMapException;
import who.tmap.toolkit.shape.MapShape;
import who.tmap.toolkit.shape.PolygonShape;
import who.tmap.toolkit.shape.annotation.BackgroundImageShape;
import who.tmap.toolkit.shape.annotation.LegendShape;
import who.tmap.toolkit.shape.annotation.TitleShape;

import com.sun.image.codec.jpeg.ImageFormatException;

/**
 * Mapping ToolKit interface
 * Takes care of all the mapping tasks in the application
 * @author stl
 */
public interface MappingToolKit extends Printable {
	
    /**
     * Set the map container (something like a JPanel)
     * @param container
     */
    void setContainer( Container container );
    Container getContainer();
    
    void repaint();
    
	// For test purpose only
	boolean isRepaintNeeded();
	void setRepaintNeeded(boolean needsRepaint);    
    
    /**
     * Paint the map
     * @param g
     */
	void paintThematicMap( Graphics2D g );
	
	void setMapVisible( boolean visible );
	boolean isMapVisible();
	
	void setCartographicDisplayVisible( boolean visible );
	boolean isCartographicDisplayVisible();
	
	void setAnnotationsVisible( boolean visible );
	boolean isAnnotationsVisible();

	void setThematicMap(ThematicMap thematicMap);			
	ThematicMap getThematicMap();
	
    TitleShape getTitleShape();
    void setTitleShape(TitleShape titleShape);

	LegendShape getLegendShape();
	void setLegendShape(LegendShape legendShape);
	
	/**
	 * Create a new shape and add it to the map
	 * @param shape
	 * @return
	 * @throws TMapException
	 */
	MapShape addShape( int shape ) throws TMapException;
	
	/**
	 * add shapes to the map
	 * @param shape
	 * @return
	 * @throws TMapException
	 */
	void addShapes( List<MapShape> shapes ) throws TMapException;
	
	/**
	 * Remove the shape
	 * @param shape the shape to remove
	 */
	void removeShape( MapShape shape );
	
	/**
	 * Get the shape containing point pt (if any)
	 * @param pt
	 * @return
	 */
	MapShape getShapeAt( Point2D pt );
	
	/**
	 * Select the shape at point pt
	 * @param pt
	 */
	MapShape selectShapeAt( Point2D pt );
	
	/**
	 * Select the required shape
	 * @param mapShape
	 */
	void selectShape( MapShape mapShape );
	
	/**
	 * Select the shapes
	 * @param mapShapes
	 */
	void selectShapes( List<MapShape> mapShapes );
	
	/**
	 * Returns the list of shapes
	 * @return
	 */
	List<MapShape> getShapes();
	
	/**
	 * Get all the shapes located inside the rectangle [p1, p2] (if any)
	 * @param p1
	 * @param p2
	 * @return
	 */
	MapShape[] getShapesAt( Point2D p1, Point2D p2 );
	
	/**
	 * Select all the shapes located inside the rectangle [p1, p2] (if any)
	 * @param p1
	 * @param p2
	 */
	void selectShapesAt( Point2D p1, Point2D p2 );
	
	/**
	 * Get the handle containing point p (if any)
	 * @param p
	 * @return
	 */
	MapShape getHandleAt( Point2D p );
	
	/**
	 * Get the currently edited shape
	 * @return
	 */
	MapShape getEditedShape();
	
	/**
	 * Set a shape to be edited
	 * @param shape
	 */
	void setEditedShape( MapShape shape );

	/**
	 * Close the polygon currently built
	 *
	 */
	void closePolygon();
	
	/**
	 * Merge the selected polygons
	 * @return the merge polygon
	 */
	MapShape mergeSelectedPolygons() throws TMapException;
	
	/**
	 * Split a polygon into two polygons
	 * @param polygon
	 * @param firstPt
	 * @param secondPt
	 * @throws TMapException
	 */
	List<MapShape> splitPolygon( PolygonShape polygon, Point2D firstPt, Point2D secondPt ) throws TMapException;
	
	/**
	 * Allows the user to select polygons using their names 
	 */
	public Map<String,PolygonShape> getPolygonsForSelectionByName();
	public void selectPolygonsSelectedByName( List<String> selectedPolygons );	
	
	/**
	 * Returns polygons with no matching data
	 * @return
	 * @throws TMapException
	 */
	Map<String, PolygonShape> getOrphanPolygons() throws TMapException;
	
	/**
	 * Returns joind id from the data with no match with the base map polygons 
	 * @return
	 */
	List<String> getNonMatchingData();
	
	/**
	 * Insert a point into a polygon
	 * @param pt
	 * @return
	 */
	//Point2D insertPolygonPoint( Point2D pt );
	
	void addDisputedBorder( Point2D pt );
	
	/**
	 * Unselect all the currently selected shapes
	 *
	 */
	void unselectShapes();
	
	/**
	 * Move the selected shapes to dragging point location
	 * @param draggingPt
	 */
	void moveSelectedShapes( Point2D draggingPt );	
	
	/**
	 * paint the selected shapes using bitmap
	 * @param g
	 */
	void paintSelectedShapes( Graphics2D g );
	
	/**
	 * Delete all the currently selected shapes
	 * Returns true if a CDPointSymbol was deleted
	 *
	 */
	boolean deleteSelectedShapes();
	
	/**
	 * Returns true if any shape is currently selected
	 * @return
	 */
	boolean anyShapeSelected();
	
	/**
	 * Returns selected shapes
	 * @return
	 */
	List<MapShape> getSelectedShapes();
	
	/**
	 * To hide selected shapes before capturing thematic map background
	 * @param selectedShapesHidden
	 */
	void setSelectedShapesHidden( boolean selectedShapesHidden );
	boolean isSelectedShapesHidden();
	
	/**
	 * Returns the rectangular bounds for the map
	 * @return
	 */
	Rectangle2D getBounds();
	
	/**
	 * Returns true if the map bounds have changed
	 * during the last repaint();
	 * @return
	 */
	boolean boundsHaveChanged();
	
	/**
	 * Copy the selected shapes to the clipboard
	 * @throws Exception 
	 *
	 */
	void clipboardCopy() throws Exception;
	
	/**
	 * Reset the map
	 *
	 */
	void reset();
	
	void setAnchor( Point2D p );
	Point2D getAnchor();
	
	void setDrag( Point2D p );
	Point2D getDrag();
	
	void xorLine( Graphics g, Point2D p1, Point2D p2 );
	void xorRectangle( Graphics g, Point2D p1, Point2D p2  );	
	void xorEllipse( Graphics g, Point2D p1, Point2D p2  );		
	
	void setCurrentColor( Color color );
	Color getCurrentColor();
	void setBackgroundColor( Color color );
	Color getBackgroundColor();
	
	/**
	 * Set User zoom factor
	 * @param factor
	 */
	void setZoomFactor( int factor );
	
	/**
	 * Retrieve User zoom factor
	 * @return
	 */
	int getZoomFactor();
	
	/**
	 * Calculates a display factor based on "real" map coordinates (minX, minY)
	 * and screen dimension (container.width, container.height)
	 * @return
	 */
	double processMapFactor();
	double processMapFactor( double width, double height );
	double getMapFactor();
	
	/**
	 * Resize the shapes so that it fits the current window
	 * without scrolling
	 *
	 */
	void fitToWindow();	
	
	void zoomIn( Point2D pt );
	void zoomOut( Point2D pt );	
	
	/**
	 * Rescale the map using new geographic box
	 * @param xmin
	 * @param xmax
	 * @param ymin
	 * @param ymax
	 */
	void updateGeographicBox( double xmin, double xmax, double ymin, double ymax );
	
	void setDefaultGeographicBox();
	 
	 /**
	  * Gets a screen point and convert it into a map point coordinates
	  * @param pt
	  * @return
	  */
	Point2D convertScreenToMap( Point2D pt );
	
	/**
	 * Gets a map point and convert it into screen coordinates
	 * @param pt
	 * @return
	 */
	Point2D convertMapToScreen( Point2D pt );
	
	void computeDigitizerFactors( double xMinD, double yMinD, double xMaxD, double yMaxD );
	Point2D convertDigitizerToMap( Point2D pt );
	
	/**
	 * Refer to "real" map coordinates (geographic box) imported from Shape File
	 * @param minX
	 */
	void setMinX( double minX );
	double getMinX();
	
	void setMinY( double minY );
	double getMinY();
	
	void setMaxX( double maxX );
	double getMaxX();
	
	void setMaxY( double maxY );
	double getMaxY();
	
	BaseMap retrieveBaseMap() throws TMapException;
	
	void paintThematicMap( Graphics2D g, Map<String, Object> annotationContext, PageFormat pf );
	
	/**
	 * Save the current thematic map as a bitmap (.gif or .jpeg) 
	 * @param file
	 * @return
	 * @throws ImageFormatException
	 * @throws IOException
	 */
    boolean saveThematicMapAsBitmap( File file, String extension, int width, int height, boolean removeBlankEdges ) throws ImageFormatException, IOException;

    BufferedImage retrieveThematicMapImage( int width, int height );    
    BufferedImage retrieveThematicMapImage( int width, 
    										int height,
    										Map<String, Object> annotationContext );
    
    void setEditMode( int editMode );
    int getEditMode();
    
    /**
     * Add coordinates
     * @param pt
     * @return the new row created in the attributes
     */
    @SuppressWarnings("unchecked")
	List addPointEntry( Point2D pt, String description );
    void selectCDPointsByDesc( List<Point2D> cdPointsDesc );
    
    /**
     * @return TMap library version
     */
    String getVersion();
    
    //void setBackgroundImageFile( File file );
    void setBackgroundImage( BackgroundImageShape bis );
    BackgroundImageShape getBackgroundImage();
    void initializeGeoBoxUsingBackgroundImage();
    
	int getDbaseJoinIdx();
	void setDbaseJoinIdx(int dbaseJoinIdx);
	
	void captureThematicMapBackground();
	void displayThematicMapBackground();
	void captureSelectedShapes(); 
	
	void projectShapes();
	
}
